<?php

namespace app\model;

use Laf\Log;
use mon\orm\Model;
use mon\util\Instance;
use mon\orm\exception\DbException;

/**
 * 资源模型
 *
 * Class Assets
 * @copyright 2021-03-24 mon-console
 * @version 1.0.0
 */
class AssetsModel extends Model
{
    use Instance;

    /**
     * 操作表
     *
     * @var string
     */
    protected $table = 'assets';

    /**
     * 存储类型对应文案
     *
     * @var array
     */
    public $storageTxt = [
        '1'     => '本地',
        '2'     => 'CDN'
    ];

    /**
     * 开放状态对应文案
     *
     * @var array
     */
    public $statusTxt = [
        '1'     => '开放',
        '2'     => '不开放'
    ];

    /**
     * 新增自动写入字段
     *
     * @var array
     */
    protected $insert = ['create_time', 'update_time'];

    /**
     * 更新自动写入字段
     *
     * @var array
     */
    protected $update = ['update_time'];

    /**
     * 补充数据
     *
     * @var array
     */
    protected $append = ['storage_txt', 'status_txt'];

    /**
     * 查询信息
     *
     * @param array $where where条件
     * @param mixed $field 查询字段
     * @return mixed
     */
    public function getInfo(array $where, $field = '*')
    {
        $info = $this->where($where)->field($field)->find();
        if (!$info) {
            $this->error = '资源不存在';
            return false;
        }

        return $info;
    }

    /**
     * 查询列表
     *
     * @param array $option 请求参数
     * @return array
     */
    public function queryList(array $option)
    {
        $limit = isset($option['limit']) ? intval($option['limit']) : 10;
        $page = isset($option['page']) && is_numeric($option['page']) ? intval($option['page']) : 1;

        // 查询
        $list = $this->scope('list', $option)->page($page, $limit)->all();
        $total = $this->scope('list', $option)->count();

        return [
            'list'      => $list->toArray(),
            'total'     => $total,
            'pageSize'  => $limit,
            'page'      => $page
        ];
    }

    /**
     * 查询列表场景
     *
     * @param mixed $query 查询实例
     * @param mixed $args  查询参数
     * @return Assets
     */
    protected function scopeList($query, $args)
    {
        // ID搜索
        if (isset($args['idx']) && is_numeric($args['idx']) && is_int($args['idx'] + 0) && $args['idx'] != '') {
            $query->where('id', intval($args['idx']));
        }
        // status搜索
        if (isset($args['status']) && is_numeric($args['status']) && is_int($args['status'] + 0) && $args['status'] != '') {
            $query->where('status', intval($args['status']));
        }
        // 按名称
        if (isset($args['title']) && is_string($args['title']) && !empty($args['title'])) {
            $query->whereLike('title', trim($args['title']) . '%');
        }
        // 按类型
        if (isset($args['storage']) && is_numeric($args['storage']) && is_int($args['storage'] + 0) && $args['storage'] != '') {
            $query->where('storage', intval($args['storage']));
        }
        // 创建时间搜索
        if (isset($args['start_time']) && is_numeric($args['start_time']) && is_int($args['start_time'] + 0) && $args['start_time'] != '') {
            $query->where('update_time', '>=', intval($args['start_time']));
        }
        if (isset($args['end_time']) && is_numeric($args['end_time']) && is_int($args['end_time'] + 0) && $args['end_time'] != '') {
            $query->where('update_time', '<=', intval($args['end_time']));
        }

        return $query;
    }

    /**
     * 新增资源
     *
     * @param array $option 请求参数
     * @param mixed $adminID 管理员ID，不为null则写入管理员日志
     * @return boolean
     */
    public function add(array $option, $adminID = null)
    {
        $check = $this->validate()->data($option)->rule([
            'title'     => ['required', 'str'],
            'url'       => ['required', 'str'],
            'storage'   => ['required', 'in:1,2'],
            'status'    => ['required', 'in:1,2']
        ])->message([
            'title'     => '请输入资源名称',
            'url'       => '请输入合法的URL',
            'storage'   => '请选择资源存储类型',
            'status'    => '请选择资源资源是否开放',
        ])->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $this->startTrans();
        try {
            $save = $this->save([
                'title'     => $option['title'],
                'url'       => $option['url'],
                'storage'   => $option['storage'],
                'status'    => $option['status']
            ], null, 'id');
            Log::instance()->oss(__FILE__, __LINE__, 'add assets, SQL => ' . $this->getLastSql(), 'sql');
            if (!$save) {
                $this->rollback();
                $this->error = '新增资源失败';
                return false;
            }

            // 管理员ID不为null，写入管理员日志
            if (!is_null($adminID)) {
                $record = AdminLogModel::instance()->record(['uid' => $adminID, 'action' => '新增资源', 'content' => '管理员新增资源：' . $option['title'] . '，资源ID：' . $save]);
                if (!$record) {
                    $this->rollback();
                    $this->error = '记录日志失败';
                    return false;
                }
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '新增资源异常';
            Log::instance()->oss(__FILE__, __LINE__, 'add assets exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 编辑资源
     *
     * @param array $option 请求参数
     * @param mixed $adminID 管理员ID，不为null则写入管理员日志
     * @return boolean
     */
    public function edit(array $option, $adminID = null)
    {
        $check = $this->validate()->data($option)->rule([
            'idx'       => ['required', 'int', 'min:1'],
            'title'     => ['required', 'str'],
            'url'       => ['required', 'str'],
            'storage'   => ['required', 'in:1,2'],
            'status'    => ['required', 'in:1,2']
        ])->message([
            'idx'       => '参数错误',
            'title'     => '请输入资源名称',
            'url'       => '请输入合法的URL',
            'storage'   => '请选择资源存储类型',
            'status'    => '请选择资源资源是否开放',
        ])->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $info = $this->getInfo(['id' => $option['idx']]);
        if (!$info) {
            return false;
        }

        $this->startTrans();
        try {
            $save = $this->save([
                'title'     => $option['title'],
                'url'       => $option['url'],
                'storage'   => $option['storage'],
                'status'    => $option['status']
            ], ['id' => $option['idx']]);
            Log::instance()->oss(__FILE__, __LINE__, 'edit assets, SQL => ' . $this->getLastSql(), 'sql');
            if (!$save) {
                $this->rollback();
                $this->error = '编辑资源信息失败';
                return false;
            }

            // 管理员ID不为null，写入管理员日志
            if (!is_null($adminID)) {
                $record = AdminLogModel::instance()->record(['uid' => $adminID, 'action' => '编辑资源', 'content' => '管理员编辑资源：' . $option['title'] . '，资源ID：' . $option['idx']]);
                if (!$record) {
                    $this->rollback();
                    $this->error = '记录日志失败';
                    return false;
                }
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '编辑资源信息异常';
            Log::instance()->oss(__FILE__, __LINE__, 'edit assets exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 自动完成create_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setCreateTimeAttr($val)
    {
        return time();
    }

    /**
     * 自动完成update_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setUpdateTimeAttr($val)
    {
        return time();
    }

    /**
     * 获取存储引擎文案
     *
     * @param mixed $value
     * @param mixed $data
     * @return string
     */
    protected function getStorageTxtAttr($value, $data)
    {
        if (!isset($data['storage'])) {
            return '';
        }
        if (!isset($this->storageTxt[$data['storage']])) {
            return $data['storage'];
        }
        return $this->storageTxt[$data['storage']];
    }

    /**
     * 获取开放状态文案
     *
     * @param mixed $value
     * @param mixed $data
     * @return string
     */
    protected function getStatusTxtAttr($value, $data)
    {
        if (!isset($data['status'])) {
            return '';
        }
        if (!isset($this->statusTxt[$data['status']])) {
            return $data['status'];
        }
        return $this->statusTxt[$data['status']];
    }
}
